package com.nulldev.util.networking.npacket4.iprotocols.atp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import com.nulldev.util.networking.npacket4.nPacket;
import com.nulldev.util.networking.npacket4.extensions.PacketExtension;

public class AudioPacket extends nPacket {

	private static final long serialVersionUID = -7519453883045501328L;

	public static enum ATPPacketType {
		NULL(-1),
		UNKNOWN(0),
		SYNC(1),
		DATA(2)

		;

		public final int id;

		private ATPPacketType(final int id) {
			this.id = id;
		}

		public static ATPPacketType get(final int id) {
			for (final ATPPacketType packet : values()) {
				if (packet.id == id)
					return packet;
			}
			return UNKNOWN;
		}
	}

	public static enum ATPPacketFlags {
		NULL(-1),
		LBM(1),
		AVP(2),
		ADSB(3),
		EAC(4),
		EAP(5),
		LPFI(6),

		;

		public final int id;

		private ATPPacketFlags(final int id) {
			this.id = id;
		}

		public static ATPPacketFlags get(final int id) {
			for (final ATPPacketFlags packet : values()) {
				if (packet.id == id)
					return packet;
			}
			return NULL;
		}
	}

	public static enum ATPPacketEncoding {
		NULL(-1),
		UNKNOWN(0),

		PCM(1),
		OPUS(2),
		VORBIS(3),
		iLBC(4),
		CODEC2(5),
		AAC(6),
		MP1(7),
		MP2(8),
		MP3(9)

		;

		public final int id;

		private ATPPacketEncoding(final int id) {
			this.id = id;
		}

		public static ATPPacketEncoding get(final int id) {
			for (final ATPPacketEncoding packet : values()) {
				if (packet.id == id)
					return packet;
			}
			return UNKNOWN;
		}
	}

	public AudioPacket(final PacketExtension... exts) {
		super("atp.data", exts);
	}

	private volatile ATPPacketEncoding encoding = ATPPacketEncoding.NULL;
	private volatile ATPPacketType type = ATPPacketType.NULL;
	private volatile ATPPacketFlags[] flags = new ATPPacketFlags[0];
	private volatile byte[][] flagData = new byte[0][0];

	// SYNC
	private volatile int bufferClearAmount;

	// DATA
	private volatile byte[] packetData;

	@Override
	public void onPacket(final DataInputStream dis) throws IOException {
		final int packetType = dis.readInt();
		this.type = ATPPacketType.get(packetType);
		switch (type) {
			case SYNC: {
				this.bufferClearAmount = dis.readInt();
				break;
			}
			case DATA: {
				this.encoding = ATPPacketEncoding.get(dis.readInt());
				final int packetLength = dis.readInt();
				final byte[] b = new byte[packetLength];
				dis.read(b, 0, b.length);
				this.packetData = b;
				break;
			}
			default: {
				break;
			}
		}
		final int flagCount = dis.readInt();
		this.flags = new ATPPacketFlags[flagCount];
		this.flagData = new byte[flagCount][];
		for (int i = 0; i < flagCount; i++) {
			this.flags[i] = ATPPacketFlags.get(dis.readInt());
		}
		for (int i = 0; i < flagCount; i++) {
			final int packetFlagDataSize = dis.readInt();
			if (packetFlagDataSize == 0)
				continue;
			else if (packetFlagDataSize < 0)
				break;
			byte[] a = new byte[packetFlagDataSize];
			dis.read(a);
			this.flagData[i] = a;
		}
	}

	public ATPPacketType getType() {
		return this.type;
	}

	public ATPPacketEncoding getEncoding() {
		return this.encoding;
	}

	public int getBufferClearAmount() {
		return this.bufferClearAmount;
	}

	public byte[] getData() {
		return this.packetData;
	}

	public byte[] dataForFlag(final int index) {
		if (index < 0 || index >= this.packetData.length) {
			return null;
		}
		return this.flagData[index];
	}

	@Override
	public void onGenerate(final DataOutputStream dos) throws IOException {
	}
}
